/**
 * HTTP客户端性能对比测试脚本
 *
 * 对比原生HttpSession和基于undici的HttpSessionV2的性能差异
 */

import type { AppointmentManagement } from '../src/shared/types/'
import type { AppConfig } from '../src/shared/types/config'
import os from 'node:os'
import { performance } from 'node:perf_hooks'
import process from 'node:process'
import { RequestBookingStrategy } from '../src/main/booking/request-strategy'
import { loadConfig, updateConfig } from '../src/main/config/index'
import { setupLogger } from '../src/main/logger/index'

// 解析参数
const count = Number.parseInt(process.argv[2] || '3', 10)
const mode = process.argv[3] || 'both' // 'native', 'undici', 'both'
// 并发参数：--concurrency N 或 --concurrency=N 或 -c N
function parseConcurrencyArg(argv: string[]): number {
  let c = 1
  const eq = argv.find(a => a.startsWith('--concurrency='))
  if (eq) {
    const val = Number.parseInt(eq.split('=')[1] || '1', 10)
    if (!Number.isNaN(val) && val > 0)
      return val
  }
  const idx = argv.findIndex(a => a === '--concurrency' || a === '-c')
  if (idx >= 0 && argv[idx + 1]) {
    const val = Number.parseInt(argv[idx + 1], 10)
    if (!Number.isNaN(val) && val > 0)
      c = val
  }
  return Math.max(1, c)
}
const concurrency = parseConcurrencyArg(process.argv)

/**
 * 创建测试用的预约数据
 */
function createTestAppointment(overrides?: Partial<AppointmentManagement>): AppointmentManagement {
  const now = new Date()
  return {
    id: Math.floor(Math.random() * 1000000),
    sequence_number: `TEST-PERF-${Date.now()}`,
    passport_number: 'CE2345678',
    license_number: '440123199012011234',
    full_name: '性能测试',
    email: 'test@example.com',
    phone_number: '21234567',
    issuing_country: 'CN',
    issuing_authority: 'GD',
    service_type: 'DI',
    preferred_dates: JSON.stringify([]),
    preferred_times: JSON.stringify([]),
    priority: 2,
    remarks: '性能测试预约',
    is_placeholder: false,
    is_monitor: false,
    appointment_status: 'pending',
    office_code: 'HKLO',
    booking_mode: 'manual',
    retry_count: 0,
    created_at: now,
    updated_at: now,
    ...overrides,
  }
}

/**
 * 获取内存使用（MB）
 */
function getMemoryMB(): number {
  return Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
}

/**
 * 获取系统可用内存（GB）
 */
function getFreeMemoryGB(): number {
  return Math.round((os.freemem() / 1024 / 1024 / 1024) * 100) / 100
}

/**
 * 运行测试
 */
async function runTest(useUndici: boolean, label: string, disableProxy: boolean = false, concurrencyLevel: number = 1): Promise<{
  totalTime: number
  avgTime: number
  memoryPeak: number
  memoryStart: number
  success: number
  failed: number
}> {
  console.log(`\n${'='.repeat(80)}`)
  console.log(`${label} - 开始测试`)
  if (disableProxy) {
    console.log('⚠️  已禁用代理，进行公平对比')
  }
  if (concurrencyLevel > 1) {
    console.log(`🚀 并发: ${concurrencyLevel}`)
  }
  console.log('='.repeat(80))

  // 设置HTTP客户端和代理
  await updateConfig({
    network: {
      use_undici: useUndici,
    },
    proxy: {
      enabled: !disableProxy,
    },
  } as Partial<AppConfig>)

  const strategy = new RequestBookingStrategy()
  const memoryStart = getMemoryMB()
  let memoryPeak = memoryStart
  const results: Array<{ success: boolean, duration: number }> = []
  const startTime = performance.now()

  // 并发执行预约
  const totalTasks = count
  let completed = 0
  const makeTask = (index: number) => async () => {
    const appointment = createTestAppointment({
      sequence_number: `TEST-PERF-${useUndici ? 'UNDICI' : 'NATIVE'}-${Date.now()}-${index}`,
    })
    const taskStart = performance.now()
    try {
      const result = await strategy.book(appointment, {
        timeoutMs: 120000,
        preferredDates: [],
        preferredTimes: [],
        disableProxy, // 禁用代理
      } as any)
      const duration = performance.now() - taskStart
      results.push({ success: result.success, duration })
      const currentMemory = getMemoryMB()
      if (currentMemory > memoryPeak)
        memoryPeak = currentMemory
      completed++
      console.log(`  [${completed}/${totalTasks}] ${result.success ? '✓' : '✗'} ${(duration / 1000).toFixed(2)}秒 | 内存: ${currentMemory}MB`)
    }
    catch (error) {
      const duration = performance.now() - taskStart
      results.push({ success: false, duration })
      completed++
      console.log(`  [${completed}/${totalTasks}] ✗ 异常: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const tasks: Array<() => Promise<void>> = []
  for (let i = 1; i <= totalTasks; i++)
    tasks.push(makeTask(i))

  // 简单并发控制器
  const worker = async () => {
    while (tasks.length > 0) {
      const next = tasks.shift()
      if (!next)
        break
      await next()
    }
  }
  const runners = Array.from({ length: Math.min(concurrencyLevel, totalTasks) }, () => worker())
  await Promise.all(runners)

  const totalTime = performance.now() - startTime
  const avgTime = results.reduce((sum, r) => sum + r.duration, 0) / results.length
  const success = results.filter(r => r.success).length
  const failed = results.length - success

  return {
    totalTime,
    avgTime,
    memoryPeak,
    memoryStart,
    success,
    failed,
  }
}

/**
 * 主函数
 */
async function main() {
  try {
    await loadConfig()
    await setupLogger()

    // 确保使用单进程模式
    await updateConfig({
      booking: {
        multiprocess: {
          enabled: false,
        },
      },
    } as Partial<AppConfig>)

    console.log('='.repeat(80))
    console.log('HTTP客户端性能对比测试')
    console.log('='.repeat(80))
    console.log(`测试数量: ${count}`)
    console.log(`测试模式: ${mode}`)
    console.log(`并发: ${concurrency}`)
    console.log(`系统信息:`)
    console.log(`  CPU核心数: ${os.cpus().length}`)
    console.log(`  可用内存: ${getFreeMemoryGB()}GB`)
    console.log(`  初始内存: ${getMemoryMB()}MB`)
    console.log('='.repeat(80))

    const results: Record<string, any> = {}

    // 检查是否需要禁用代理（如果原生版本因为代理失败）
    const disableProxy = process.argv.includes('--no-proxy')

    if (mode === 'native' || mode === 'both') {
      results.native = await runTest(false, '原生HttpSession (node:http/https)', disableProxy, concurrency)
    }

    if (mode === 'undici' || mode === 'both') {
      results.undici = await runTest(true, '高性能HttpSessionV2 (undici)', disableProxy, concurrency)
    }

    // 打印对比报告
    console.log(`\n${'='.repeat(80)}`)
    console.log('性能对比报告')
    console.log('='.repeat(80))

    if (results.native) {
      console.log(`\n原生HttpSession:`)
      console.log(`  总耗时: ${(results.native.totalTime / 1000).toFixed(2)}秒`)
      console.log(`  平均耗时: ${(results.native.avgTime / 1000).toFixed(2)}秒/个`)
      console.log(`  内存使用: ${results.native.memoryStart}MB → ${results.native.memoryPeak}MB (增长 ${results.native.memoryPeak - results.native.memoryStart}MB)`)
      console.log(`  成功率: ${results.native.success}/${count} (${Math.round((results.native.success / count) * 100)}%)`)
    }

    if (results.undici) {
      console.log(`\n高性能HttpSessionV2 (undici):`)
      console.log(`  总耗时: ${(results.undici.totalTime / 1000).toFixed(2)}秒`)
      console.log(`  平均耗时: ${(results.undici.avgTime / 1000).toFixed(2)}秒/个`)
      console.log(`  内存使用: ${results.undici.memoryStart}MB → ${results.undici.memoryPeak}MB (增长 ${results.undici.memoryPeak - results.undici.memoryStart}MB)`)
      console.log(`  成功率: ${results.undici.success}/${count} (${Math.round((results.undici.success / count) * 100)}%)`)
    }

    if (results.native && results.undici) {
      console.log(`\n性能提升:`)
      const timeImprovement = ((results.native.totalTime - results.undici.totalTime) / results.native.totalTime * 100).toFixed(1)
      const memoryImprovement = results.native.memoryPeak - results.undici.memoryPeak
      console.log(`  总耗时: ${timeImprovement}% ${timeImprovement.startsWith('-') ? '变慢' : '更快'}`)
      console.log(`  平均耗时: ${((results.native.avgTime - results.undici.avgTime) / results.native.avgTime * 100).toFixed(1)}% ${results.native.avgTime > results.undici.avgTime ? '更快' : '变慢'}`)
      console.log(`  内存节省: ${memoryImprovement > 0 ? `${memoryImprovement}MB` : `${Math.abs(memoryImprovement)}MB 增加`}`)
    }

    console.log(`\n${'='.repeat(80)}`)
    console.log('测试完成')
    console.log('='.repeat(80))

    process.exit(0)
  }
  catch (error) {
    console.error('\n❌ 测试执行失败:', error)
    if (error instanceof Error) {
      console.error(error.stack)
    }
    process.exit(1)
  }
}

main().catch(console.error)
